"""1688商品搜索爬虫主模块"""

import time
import logging
from typing import List, Optional
from urllib.parse import quote

from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.common.exceptions import TimeoutException, NoSuchElementException
from bs4 import BeautifulSoup

from .models import ProductInfo, SearchResult
from .anti_crawler import AntiCrawlerHandler
from .utils import (
    clean_text, extract_price, extract_sales, is_guangzhou_location,
    validate_url, filter_guangzhou_products, sort_by_sales
)
from config.settings import Settings


class Product1688Spider:
    """1688商品搜索爬虫"""
    
    def __init__(self, platform: str = '1688', headless: bool = True, verbose: bool = False):
        """初始化爬虫
        
        Args:
            platform: 平台名称 ('1688', 'taobao', 'jd')
            headless: 是否无头模式运行
            verbose: 是否详细输出
        """
        self.settings = Settings()
        self.platform = platform
        self.platform_config = self.settings.PLATFORMS.get(platform, self.settings.PLATFORMS['taobao'])
        self.anti_crawler = AntiCrawlerHandler()
        self.driver: Optional[webdriver.Chrome] = None
        self.headless = headless
        self.verbose = verbose
        self.logger = self._setup_logger()
        
    def _setup_logger(self) -> logging.Logger:
        """设置日志记录器"""
        logger = logging.getLogger(__name__)
        logger.setLevel(getattr(logging, self.settings.LOG_LEVEL))
        
        if not logger.handlers:
            handler = logging.StreamHandler()
            formatter = logging.Formatter(
                '%(asctime)s - %(name)s - %(levelname)s - %(message)s'
            )
            handler.setFormatter(formatter)
            logger.addHandler(handler)
        
        return logger
    
    def _init_driver(self) -> None:
        """初始化浏览器驱动"""
        if self.driver is None:
            self.logger.info("初始化浏览器驱动...")
            self.driver = self.anti_crawler.create_driver(headless=self.headless)
            self.driver.implicitly_wait(self.settings.ELEMENT_WAIT_TIMEOUT)
    
    def _close_driver(self) -> None:
        """关闭浏览器驱动"""
        if self.driver:
            self.driver.quit()
            self.driver = None
    
    def _navigate_to_search(self, keyword: str, page: int = 1) -> bool:
        """导航到搜索页面"""
        try:
            # 先访问首页建立会话
            if self.platform == '1688':
                self.logger.info("先访问1688首页建立会话")
                self.driver.get("https://www.1688.com")
            elif self.platform == 'taobao':
                self.logger.info("先访问淘宝首页建立会话")
                self.driver.get("https://www.taobao.com")
            elif self.platform == 'jd':
                self.logger.info("先访问京东首页建立会话")
                self.driver.get("https://www.jd.com")
            time.sleep(3)
            
            # 构建搜索URL
            search_url = self._get_search_url(keyword, page)
            
            self.logger.info(f"访问搜索页面: {search_url}")
            self.driver.get(search_url)
            
            # 等待页面加载
            WebDriverWait(self.driver, self.settings.PAGE_LOAD_TIMEOUT).until(
                EC.presence_of_element_located((By.CSS_SELECTOR, "body"))
            )
            
            # 检查是否需要验证码或其他反爬措施
            if "验证" in self.driver.title or "captcha" in self.driver.current_url.lower():
                self.logger.warning("检测到验证码页面，需要人工处理")
                return False
            
            # 检查是否需要登录
            if "login" in self.driver.current_url.lower() or "登录" in self.driver.title:
                self.logger.warning("检测到登录页面，尝试跳过")
                # 尝试点击跳过登录按钮
                try:
                    skip_buttons = self.driver.find_elements(By.CSS_SELECTOR, ".close, .skip, [class*='close'], [class*='skip'], .login-skip")
                    for btn in skip_buttons:
                        try:
                            btn.click()
                            time.sleep(2)
                            break
                        except:
                            continue
                except Exception as e:
                    self.logger.debug(f"尝试跳过登录失败: {e}")
            
            return True
            
        except TimeoutException:
            self.logger.error(f"页面加载超时: {keyword}, 页面 {page}")
            return False
        except Exception as e:
            self.logger.error(f"导航到搜索页面时出错: {e}")
            return False
    
    def _get_search_url(self, keyword: str, page: int, sort_by_sales: bool = True) -> str:
        """构建搜索URL"""
        encoded_keyword = quote(keyword)
        
        if self.platform == 'taobao':
            # 淘宝搜索URL，s参数表示起始位置（每页44个商品）
            start = (page - 1) * 44
            url = f"https://s.taobao.com/search?q={encoded_keyword}&s={start}"
            if sort_by_sales:
                url += '&sort=sale-desc'
            return url
        elif self.platform == 'jd':
            # 京东搜索URL
            url = f"https://search.jd.com/Search?keyword={encoded_keyword}&page={page}"
            if sort_by_sales:
                url += '&psort=3'  # 按销量排序
            return url
        else:
            # 1688搜索URL
            return f"https://s.1688.com/selloffer/offer_search.htm?keywords={encoded_keyword}&beginPage={page}&sortType=va_rmdesc&tab=offer"
    
    def _wait_for_products_load(self) -> bool:
        """等待商品列表加载完成"""
        # 检查是否需要登录（主要针对1688）
        if self.platform == '1688':
            try:
                login_elements = self.driver.find_elements(By.CSS_SELECTOR, "[class*='login'], .login-box, #login")
                if login_elements:
                    self.logger.warning("检测到登录页面，尝试跳过登录")
                    skip_buttons = self.driver.find_elements(By.CSS_SELECTOR, ".close, .skip, [class*='close'], [class*='skip']")
                    for btn in skip_buttons:
                        try:
                            btn.click()
                            time.sleep(2)
                            break
                        except:
                            continue
            except Exception as e:
                self.logger.debug(f"检查登录状态失败: {e}")
        
        # 使用平台特定的选择器
        if self.platform == '1688':
            selectors_to_try = [
                '.offer-item',
                '.sm-offer-item', 
                '.card-item',
                '.offer-wrapper',
                '[data-widget-cid="widget.offer.offerResultItem"]',
                '.list-item'
            ]
        elif self.platform == 'taobao':
            selectors_to_try = [
                '.item',
                '.item-wrapper',
                '[data-category="auctions"]',
                '.grid-item',
                '.product'
            ]
        elif self.platform == 'jd':
            selectors_to_try = [
                '.gl-item',
                '.goods-item',
                '.item',
                '.product-item'
            ]
        else:
            selectors_to_try = [
                '.offer-item',
                '.sm-offer-item', 
                '.card-item',
                '.offer-wrapper',
                '[data-widget-cid="widget.offer.offerResultItem"]',
                '.list-item'
            ]
        
        products_found = False
        for selector in selectors_to_try:
            try:
                WebDriverWait(self.driver, 5).until(
                    EC.presence_of_element_located((By.CSS_SELECTOR, selector))
                )
                self.logger.info(f"商品列表加载成功，使用选择器: {selector}")
                products_found = True
                break
            except TimeoutException:
                continue
                
        if not products_found:
            self.logger.warning("商品列表加载超时，尝试了所有选择器")
            return False
            
        # 额外等待确保内容完全加载
        time.sleep(2)
        return True
    
    def _extract_products_from_page(self) -> List[ProductInfo]:
        """从当前页面提取商品信息"""
        products = []
        
        try:
            # 使用平台特定的选择器
            if self.platform == '1688':
                selectors_to_try = [
                    '.offer-item',
                    '.sm-offer-item', 
                    '.card-item',
                    '.offer-wrapper',
                    '[data-widget-cid="widget.offer.offerResultItem"]',
                    '.list-item',
                    '[class*="offer"]',
                    '[class*="item"]'
                ]
            elif self.platform == 'taobao':
                selectors_to_try = [
                    '.item',
                    '.item-wrapper',
                    '[data-category="auctions"]',
                    '.grid-item',
                    '.product'
                ]
            elif self.platform == 'jd':
                selectors_to_try = [
                    '.gl-item',
                    '.goods-item',
                    '.item',
                    '.product-item'
                ]
            else:
                selectors_to_try = [
                    '.offer-item',
                    '.sm-offer-item', 
                    '.card-item',
                    '.offer-wrapper',
                    '[data-widget-cid="widget.offer.offerResultItem"]',
                    '.list-item',
                    '[class*="offer"]',
                    '[class*="item"]'
                ]
            
            product_elements = []
            for selector in selectors_to_try:
                elements = self.driver.find_elements(By.CSS_SELECTOR, selector)
                if elements:
                    self.logger.info(f"使用选择器 {selector} 找到 {len(elements)} 个商品元素")
                    product_elements = elements
                    break
            
            if not product_elements:
                self.logger.warning(f"未找到任何{self.platform}平台的商品元素")
                return products
            
            for i, element in enumerate(product_elements):
                try:
                    product_info = self._extract_single_product(element)
                    if product_info:
                        products.append(product_info)
                        if getattr(self, 'verbose', False):
                            self.logger.info(f"提取商品 {i+1}: {product_info.title[:50]}...")
                except Exception as e:
                    self.logger.warning(f"提取第 {i+1} 个商品信息失败: {e}")
                    continue
                    
        except Exception as e:
            self.logger.error(f"提取商品信息失败: {e}")
            
        return products
    
    def _extract_single_product(self, element) -> Optional[ProductInfo]:
        """从单个商品元素提取信息"""
        try:
            # 使用平台特定的选择器
            if self.platform == '1688':
                title_selectors = [
                    "a[title]", ".title a", ".offer-title a", "h3 a", "h4 a", 
                    ".product-title a", "[class*='title'] a", "a"
                ]
                price_selectors = [
                    ".price-num", ".price", ".offer-price", ".money", ".cost",
                    "[class*='price']", "[data-price]", ".yuan", ".rmb"
                ]
                sales_selectors = [
                    ".sale-num", ".sales", ".sold", "[class*='sale']", 
                    "[class*='sold']", "[data-sales]", ".deal"
                ]
            elif self.platform == 'taobao':
                title_selectors = [
                    ".title a", ".item-title a", "h3 a", "a[title]", 
                    "[class*='title'] a", ".product-title a"
                ]
                price_selectors = [
                    ".price", ".price-current", "[class*='price']", ".money"
                ]
                sales_selectors = [
                    ".deal-cnt", ".sales", "[class*='sales']", ".sold"
                ]
            elif self.platform == 'jd':
                title_selectors = [
                    ".p-name a", ".item-title a", "h3 a", "a[title]", 
                    "[class*='title'] a", ".product-title a"
                ]
                price_selectors = [
                    ".p-price", ".price", "[class*='price']", ".money"
                ]
                sales_selectors = [
                    ".p-commit", ".sales", "[class*='sales']", ".sold"
                ]
            else:
                title_selectors = [
                    "a[title]", ".title a", ".offer-title a", "h3 a", "h4 a", 
                    ".product-title a", "[class*='title'] a", "a"
                ]
                price_selectors = [
                    ".price-num", ".price", ".offer-price", ".money", ".cost",
                    "[class*='price']", "[data-price]", ".yuan", ".rmb"
                ]
                sales_selectors = [
                    ".sale-num", ".sales", ".sold", "[class*='sale']", 
                    "[class*='sold']", "[data-sales]", ".deal"
                ]
            
            # 提取标题和链接
            title = "未知"
            link = ""
            
            for selector in title_selectors:
                try:
                    title_element = element.find_element(By.CSS_SELECTOR, selector)
                    title = title_element.get_attribute('title') or title_element.text.strip()
                    link = title_element.get_attribute('href') or ""
                    if title and title != "未知":
                        break
                except:
                    continue
            
            # 如果没有找到链接，尝试其他方式
            if not link:
                try:
                    link_element = element.find_element(By.CSS_SELECTOR, "a[href]")
                    link = link_element.get_attribute('href')
                except:
                    pass
            
            # 处理相对链接
            if link:
                if link.startswith('//'):
                    link = 'https:' + link
                elif link.startswith('/') and self.platform == '1688':
                    link = 'https://detail.1688.com' + link
                elif link.startswith('/') and self.platform == 'taobao':
                    link = 'https:' + link
                elif link.startswith('/') and self.platform == 'jd':
                    link = 'https://item.jd.com' + link
            
            # 提取价格
            price = "未知"
            for selector in price_selectors:
                try:
                    price_element = element.find_element(By.CSS_SELECTOR, selector)
                    price_text = price_element.text.strip()
                    if price_text and any(char.isdigit() for char in price_text):
                        price = price_text
                        break
                except:
                    continue
            
            # 提取销量
            sales = "未知"
            for selector in sales_selectors:
                try:
                    sales_element = element.find_element(By.CSS_SELECTOR, selector)
                    sales_text = sales_element.text.strip()
                    if sales_text and any(char.isdigit() for char in sales_text):
                        sales = sales_text
                        break
                except:
                    continue
            
            # 提取图片
            image_url = ""
            try:
                img_selectors = ["img[src]", "img[data-src]", "img"]
                for selector in img_selectors:
                    try:
                        img_element = element.find_element(By.CSS_SELECTOR, selector)
                        image_url = (img_element.get_attribute('src') or 
                                   img_element.get_attribute('data-src') or 
                                   img_element.get_attribute('data-original') or "")
                        if image_url and ('http' in image_url or image_url.startswith('//')): 
                            if image_url.startswith('//'):
                                image_url = 'https:' + image_url
                            break
                    except:
                        continue
            except:
                pass
            
            # 平台特定字段
            if self.platform == '1688':
                # 1688特有字段：发货地、供应商、最小起订量
                location_selectors = [
                    ".location", ".area", ".region", "[class*='location']", 
                    "[class*='area']", "[class*='address']", ".city", ".province"
                ]
                location = "未知"
                for selector in location_selectors:
                    try:
                        location_element = element.find_element(By.CSS_SELECTOR, selector)
                        location_text = location_element.text.strip()
                        if location_text and len(location_text) > 1:
                            location = location_text
                            break
                    except:
                        continue
                
                supplier_selectors = [
                    ".company-name", ".supplier", ".shop-name", "[class*='company']", 
                    "[class*='supplier']", "[class*='shop']", ".store-name"
                ]
                supplier = "未知"
                for selector in supplier_selectors:
                    try:
                        supplier_element = element.find_element(By.CSS_SELECTOR, selector)
                        supplier_text = supplier_element.text.strip()
                        if supplier_text and len(supplier_text) > 1:
                            supplier = supplier_text
                            break
                    except:
                        continue
                
                min_order_selectors = [
                    ".min-order", ".moq", ".minimum", "[class*='min']", 
                    "[class*='order']", "[data-moq]", ".quantity"
                ]
                min_order = "未知"
                for selector in min_order_selectors:
                    try:
                        min_order_element = element.find_element(By.CSS_SELECTOR, selector)
                        min_order_text = min_order_element.text.strip()
                        if min_order_text and any(char.isdigit() for char in min_order_text):
                            min_order = min_order_text
                            break
                    except:
                        continue
            else:
                # 其他平台的通用字段
                location = "未知"
                supplier = "未知"
                min_order = "未知"
            
            # 只有当标题不为空且不是"未知"时才返回商品信息
            if title and title.strip() and title != "未知":
                return ProductInfo(
                    title=title,
                    price=price,
                    sales=sales,
                    location=location,
                    supplier=supplier,
                    product_url=link,
                    image_url=image_url,
                    min_order=min_order
                )
            else:
                return None
            
        except Exception as e:
            self.logger.warning(f"提取商品信息失败: {e}")
            return None
    
    def _parse_product_element(self, element) -> Optional[ProductInfo]:
        """解析单个商品元素"""
        try:
            # 提取商品标题和链接
            title_selectors = [
                "a[title]", ".title a", ".offer-title a", 
                "[class*='title'] a", "h3 a", "h4 a"
            ]
            
            title = ""
            product_url = ""
            
            for selector in title_selectors:
                title_elem = element.select_one(selector)
                if title_elem:
                    title = clean_text(title_elem.get('title', '') or title_elem.get_text())
                    href = title_elem.get('href', '')
                    if href:
                        product_url = validate_url(href, self.settings.BASE_URL)
                    break
            
            if not title or not product_url:
                return None
            
            # 提取价格
            price_selectors = [
                ".price", ".offer-price", "[class*='price']", ".money"
            ]
            price = ""
            for selector in price_selectors:
                price_elem = element.select_one(selector)
                if price_elem:
                    price = extract_price(price_elem.get_text())
                    break
            
            # 提取销量
            sales_selectors = [
                ".sales", ".offer-sales", "[class*='sales']", ".deal"
            ]
            sales = ""
            for selector in sales_selectors:
                sales_elem = element.select_one(selector)
                if sales_elem:
                    sales = extract_sales(sales_elem.get_text())
                    break
            
            # 提取发货地
            location_selectors = [
                ".location", ".offer-location", "[class*='location']", ".address"
            ]
            location = ""
            for selector in location_selectors:
                location_elem = element.select_one(selector)
                if location_elem:
                    location = clean_text(location_elem.get_text())
                    break
            
            # 提取供应商
            supplier_selectors = [
                ".supplier", ".offer-supplier", "[class*='supplier']", ".company"
            ]
            supplier = ""
            for selector in supplier_selectors:
                supplier_elem = element.select_one(selector)
                if supplier_elem:
                    supplier = clean_text(supplier_elem.get_text())
                    break
            
            # 提取图片
            img_elem = element.select_one("img")
            image_url = ""
            if img_elem:
                src = img_elem.get('src', '') or img_elem.get('data-src', '')
                if src:
                    image_url = validate_url(src)
            
            # 提取最小起订量
            min_order_selectors = [
                ".min-order", "[class*='min']", ".moq"
            ]
            min_order = ""
            for selector in min_order_selectors:
                min_order_elem = element.select_one(selector)
                if min_order_elem:
                    min_order = clean_text(min_order_elem.get_text())
                    break
            
            return ProductInfo(
                title=title,
                price=price,
                min_order=min_order,
                sales=sales,
                location=location,
                supplier=supplier,
                product_url=product_url,
                image_url=image_url
            )
            
        except Exception as e:
            self.logger.error(f"解析商品元素时出错: {e}")
            return None
    
    def search_products(
        self, 
        keyword: str, 
        max_pages: int = None,
        sort_by_sales: bool = True,
        filter_guangzhou: bool = True
    ) -> SearchResult:
        """搜索商品"""
        if max_pages is None:
            max_pages = self.settings.MAX_PAGES
        
        self.logger.info(f"开始搜索商品: {keyword}, 最大页数: {max_pages}")
        
        all_products = []
        
        try:
            self._init_driver()
            
            for page in range(1, max_pages + 1):
                self.logger.info(f"正在爬取第 {page} 页...")
                
                # 导航到搜索页面
                if not self._navigate_to_search(keyword, page):
                    self.logger.error(f"无法访问第 {page} 页，跳过")
                    continue
                
                # 等待页面加载
                if not self._wait_for_products_load():
                    self.logger.warning(f"第 {page} 页商品加载失败，跳过")
                    continue
                
                # 提取商品信息
                page_products = self._extract_products_from_page()
                if page_products:
                    all_products.extend(page_products)
                    self.logger.info(f"第 {page} 页获取到 {len(page_products)} 个商品")
                else:
                    self.logger.warning(f"第 {page} 页未获取到商品")
                
                # 反爬延时
                self.anti_crawler.adaptive_delay()
            
        except Exception as e:
            self.logger.error(f"搜索过程中出错: {e}")
        
        finally:
            self._close_driver()
        
        # 数据处理
        self.logger.info(f"原始商品数量: {len(all_products)}")
        
        # 筛选广州发货的商品
        if filter_guangzhou:
            all_products = filter_guangzhou_products(all_products)
            self.logger.info(f"筛选广州发货后商品数量: {len(all_products)}")
        
        # 按销量排序
        if sort_by_sales:
            from .utils import sort_by_sales as sort_products_by_sales
            all_products = sort_products_by_sales(all_products, reverse=True)
            self.logger.info("已按销量降序排序")
        
        result = SearchResult(
            keyword=keyword,
            total_count=len(all_products),
            products=all_products
        )
        
        self.logger.info(f"搜索完成，共获取 {len(all_products)} 个商品")
        return result
    
    def __enter__(self):
        """上下文管理器入口"""
        return self
    
    def __exit__(self, exc_type, exc_val, exc_tb):
        """上下文管理器出口"""
        self._close_driver()